기본 Bloom Texture에 접근할 수 없는 문제
1. 문제
- FSceneViewExtensionBase를 이용하여 Custom Lens Flare를 개발할 때, 엔진 기본 Bloom Texture에 접근할 수 없다는 문제가 있음
2. 시도
나는 Bloom을 재현해서 내 커스텀 포스트 프로세스 패스에 추가하기로 결정하였음.
2.1. 기본 Bloom 분석
일단 Bloom을 분석하기 위해 RenderDoc을 사용함

프레임을 분석해 보면 Bloom은 3단계로 렌더링 할 수 있음
- BloomSetup 단계에서 Half-size SceneColor를 가공
- BloomSetup 텍스처를 다운 샘플링.(1/4 ~ 1/64)
- 다운샘플링된 텍스처에 GaussianBlur를 하여 Bloom 텍스처 렌더링
소스코드 분석은 PostProcessing.cpp 파일의 1261줄부터 BloomSetup이 시작된다. (5.5.4 버전)
if (bFFTBloomEnabled)
{
[...]
}
else
{
[...]
// Line 1261, 1. Bloom Setup
DownsampleInput = FScreenPassTextureSlice::CreateFromScreenPassTexture(GraphBuilder, AddBloomSetupPass(GraphBuilder, View, SetupPassInputs));
}
const bool bLogLumaInAlpha = false;
// 2. 다운 샘플링
BloomDownsampleChain.Init(GraphBuilder, View, EyeAdaptationParameters, DownsampleInput, DownsampleChainQuality, bLogLumaInAlpha);
LensFlareSceneDownsampleChain = &BloomDownsampleChain;
}
// 3. Bloom 렌더링
Bloom = AddGaussianBloomPasses(GraphBuilder, View, LensFlareSceneDownsampleChain);
}
이 부분부터 시작해 함수를 추적하며
- PostProcessing.cpp
- PostProcessingBloomSetup.cpp
- PostProcessBloom.usf
- FilterPixelShader.usf
이파일들 위주로 분석하면 된다.
참고로,if (bFFTBloomEnabled)블록은 공식 문서에 따르면 게임 어플리케이션에선 잘 사용되지 않는 옵션이다.

2.2. 구현
[...]
// Line 257
if (bBloom)
{
HalfSceneColor = AddTyTDownSamplePass(
GraphBuilder,
ViewInfo,
TEXT("Half Res Scene Color"),
SceneColorTexture.Texture,
Viewport
);
FTyTBloomDownSampleChain BloomDownSampleChain;
BloomDownSampleChain.Init(
GraphBuilder,
ViewInfo,
AddTyTBloomSetupPass(GraphBuilder, ViewInfo, HalfSceneColor, HalfResViewport),
HalfResViewport
);
Bloom = AddTyTGaussianBloomPass(GraphBuilder, ViewInfo, BloomDownSampleChain);
}
[...]
[...]
FRDGTextureRef AddTyTBloomSetupPass(
FRDGBuilder& GraphBuilder,
const FViewInfo& ViewInfo,
FRDGTextureRef HalfResSceneColor,
const FIntRect& HalfResViewport
)
{
// Unreal Insights
RDG_GPU_STAT_SCOPE(GraphBuilder, TyTBloomSetup);
// Render Doc
RDG_EVENT_SCOPE(GraphBuilder, "TyTBloomSetup");
const FTyTBloomSettings* Settings = UTyTPostProcessSettingsAsset::GetBloomSettings();
float Threshold = Settings ? Settings->Threshold : -1;
const bool bThresholdEnabled = Threshold > -1;
FRDGTextureDesc TextureDesc;
TextureDesc.Reset();
TextureDesc.Extent = HalfResViewport.Size();
TextureDesc.Format = EPixelFormat::PF_FloatRGB;
TextureDesc.ClearValue = FClearValueBinding::Black;
FRDGTextureRef OutTexture = GraphBuilder.CreateTexture(TextureDesc, TEXT("TyTBloomSetup"));
FTyTBloomSetupPS::FParameters* Parameters = GraphBuilder.AllocParameters<FTyTBloomSetupPS::FParameters>();
Parameters->ViewUniformShaderParameters = ViewInfo.ViewUniformBuffer;
Parameters->InputTexture = HalfResSceneColor;
Parameters->InputSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
Parameters->BloomThreshold = Threshold;
Parameters->RenderTargets[0] = FRenderTargetBinding(OutTexture, ERenderTargetLoadAction::ELoad);
FTyTBloomSetupPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTyTBloomSetupPS::FThresholdDim>(bThresholdEnabled);
TShaderMapRef<FTyTScreenPassVS> VS(ViewInfo.ShaderMap);
TShaderMapRef<FTyTBloomSetupPS> PS(ViewInfo.ShaderMap, PermutationVector);
AddTyTScreenPass(
GraphBuilder,
TEXT("TyTBloomSetup(1/2)"),
Parameters,
VS,
PS,
TStaticBlendState<>::GetRHI(),
HalfResViewport
);
return OutTexture;
}
[...]
2.3. 기존 Bloom 비활성화
가장 초기 상태에서, PostProcessVolume이 레벨에 존재하지 않더라도 Bloom은 기본적으로 적용되어 있다. 따라서 PostProcessVolume을 추가하여 수동으로 꺼주어야 한다.

Bloom 효과를 제거한 모습이다.
3. 결과
- 렌즈 플레어 효과에 구현될 Bloom 효과 구현
- Bloom 또한 커스텀이 가능함
- 기존 PostProcess에서 Bloom효과를 꺼줘야 하는 번거로움 발생
- FFT같은 고사양 Bloom은 따로 구현해야함
기본 블룸

커스텀 블룸
